//T40,T41,仔细研究


#include "BlockQueue.hpp"  // 包含阻塞队列头文件，实现生产者-消费者同步
#include "Thread.hpp"     // 包含线程类头文件，用于创建和管理线程
#include "Task.hpp"       // 包含任务类头文件，定义了任务的结构
#include <string>         // 字符串处理
#include <vector>         // 动态数组容器
#include <unistd.h>       // Unix标准函数库，提供sleep等系统调用
#include <ctime>          // 时间相关函数

using namespace ThreadModule;  // 使用ThreadModule命名空间,不需要重复写ThreadModule::前缀
int a = 10;  // 全局变量
using blockqueue_t = BlockQueue<Task>;  // 定义Task类型的阻塞队列类型别名

// 定义一个简单的任务函数，打印hello world
void PrintHello()
{
    std::cout << "hello world" << std::endl;
}
// class ThreadData
// {
// private:
//     blockqueue_t &bq;
//     std::string who;
// };


// 修改Consumer函数，添加线程ID显示
void Consumer(blockqueue_t &bq)
{
    // 获取线程ID并截取最后几位以便显示
    pthread_t tid = pthread_self();
    int short_tid = tid % 10000;
    
    std::cout << "消费者线程[" << short_tid << "] 已启动" << std::endl;
    
    while (true)
    {
        // 1. 从blockqueue取下来任务
        Task t;
        bq.Pop(&t);
        
        // 2. 处理这个任务前显示线程ID
        std::cout << "消费者线程[" << short_tid << "] 开始执行任务" << std::endl;
        
        // 3. 执行任务
        t();
        
        // 4. 任务执行后显示完成信息
        std::cout << "消费者线程[" << short_tid << "] 完成任务" << std::endl;
    }
}

// 修改Productor函数，添加线程ID显示
void Productor(blockqueue_t &bq)
{
    // 获取线程ID并截取最后几位以便显示
    pthread_t tid = pthread_self();
    int short_tid = tid % 10000;
    
    std::cout << "生产者线程[" << short_tid << "] 已启动" << std::endl;
    
    srand(time(nullptr)^pthread_self());
    while (true)
    {
        sleep(1);
        
        // 创建任务
        Task t = PrintHello;
        
        // 显示生产者线程信息
        std::cout << "生产者线程[" << short_tid << "] 生产了一个新任务" << std::endl;
        
        // 将任务放入队列
        bq.Enqueue(t);
    }
}

// 通用线程启动函数，创建指定数量的线程并启动
void StartComm(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq, func_t<blockqueue_t> func)
{
    for (int i = 0; i < num; i++)  // 循环创建num个线程
    {
        std::string name = "thread-" + std::to_string(i + 1);  // 生成线程名称
        threads->emplace_back(func, bq, name);  // 创建线程对象并添加到vector中
        threads->back().Start();  // 启动刚刚创建的线程
    }
}

// 启动指定数量的消费者线程
void StartConsumer(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq)
{
    StartComm(threads, num, bq, Consumer);  // 调用通用启动函数，传入消费者函数
}

// 启动指定数量的生产者线程
void StartProductor(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq)
{
    StartComm(threads, num, bq, Productor);  // 调用通用启动函数，传入生产者函数
}

// 等待所有线程完成
void WaitAllThread(std::vector<Thread<blockqueue_t>> &threads)
{
    for (auto &thread : threads)  // 遍历所有线程
    {
        thread.Join();  // 调用Join方法等待线程结束
    }
}

int main()
{
    blockqueue_t *bq = new blockqueue_t(5);  // 创建容量为5的阻塞队列
    std::vector<Thread<blockqueue_t>> threads;  // 创建线程容器
    // std::vector<Thread<ThreadData>> threads;

    StartConsumer(&threads, 3, *bq);  // 启动3个消费者线程
    StartProductor(&threads, 1, *bq);  // 启动1个生产者线程
    WaitAllThread(threads);  // 等待所有线程完成（实际上这些线程是无限循环的，不会自然结束）

    return 0;
}